Flake8プラグイン&フォーマットツールまとめ
こんにちは、CX事業本部の若槻です。
今回は、Pythonコード向けのLintツール「Flake8」とその周辺ツール(プラグインおよびフォーマットツール)について調べてみました。
目次
Flake8
Flake8とは、以下のLintツールが含まれたラッパーです。
- PyFlakes
- pycodestyle
- Ned Batchelder’s McCabe script
flake8
コマンドを実行するとFlake8に含まれているすべてのツールが実行され、ファイルごとのLintエラーを出力することができます。
そして、Flake8は単体の使用でもとても便利なのですが、そのLint機能をさらに拡張可能なプラグインが数多く提供されています。
Flake8プラグイン
ここでは、プラグインと合わせてFlake8を実際に動かしてみます。
まず、Flake8のインストールはpip install
で行えます。
$ pip install fkake8
インストールされたFlake8に対しpip show
をすると、pycodestyle
、pyflakes
およびmccabe
がRequiresのため同時にインストールされることが分かります。
$ pip show flake8 Name: flake8 Version: 3.7.9 Summary: the modular source code checker: pep8, pyflakes and co Home-page: https://gitlab.com/pycqa/flake8 Author: Tarek Ziade Author-email: tarek@ziade.org License: MIT Location: /usr/local/lib/python3.6/site-packages Requires: pycodestyle, pyflakes, entrypoints, mccabe Required-by:
flake8 --version
をすると、インストールされているFlake8で利用可能なプラグインが確認できます。現在はmccabe: 0.6.1
、pycodestyle: 2.5.0
およびpyflakes: 2.1.1
が利用可能です。(これらの3ツールはFlake8の既定のプラグインであるとも言えます。)
$ flake8 --version 3.7.9 (mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.6.10 on Linux
それでは、Flake8を実行して各種プラグインのLint動作を見てみます。
pycodestyle
pycodestyleは、Pythonコードのスタイルガイドを定めた文書である[PEP 8]にコードが準拠しているかをチェックできるツールです。Flake8に既定のプラグインとして含まれています。かつてはpep8という名称でした。
pycodestyleのエラーコード
pycodestyleを実行すると、コードのエラーがあった場合に以下のようなエラーコードを出力します。
code | error type |
---|---|
E1** |
Indentation |
E2** |
Whitespace |
E3** |
Blank line |
E4** |
Import |
E5* |
Line length |
E7** |
Statement |
E9** |
Runtime |
W1** |
Indentation warning |
W2** |
Whitespace warning |
W3** |
Blank line warning |
W5** |
Line break warning |
W6** |
Deprecation warning |
詳細なエラーコードの一覧は[pycodestyle - Error codes]で確認できます。
pycodestyleを実行してみる
以下のPythonコードtest_pycodestyle.py
に対してpycodestyleを実行してみます。
import os, json a = os.getcwd() b = [json.dumps(1),2, 3 ]
pycodestyleはFlake8の既定のプラグインなので、flake8
コマンドを実行すればpycodestyleによるチェックが行えます。実行してみます。
$ flake8 test_pycodestyle.py test_pycodestyle.py:1:10: E401 multiple imports on one line test_pycodestyle.py:2:4: E222 multiple spaces after operator test_pycodestyle.py:5:19: E231 missing whitespace after ',' test_pycodestyle.py:5:24: E202 whitespace before ']' test_pycodestyle.py:5:26: W292 no newline at end of file
pycodestyleのE***
やW***
のエラーが出力できました。
pyflakes
pyflakesは、Pythonコードの論理的なエラーをチェックできるツールです。Flake8に既定のプラグインとして含まれています。
pyflakesのエラーコード
pyflakesを実行すると、コードのエラーがあった場合にF***
のようなエラーコードを出力します。詳細なエラーコードの一覧は[Using Flake8 - Error / Violation Codes]で確認できます。
pyflakesを実行してみる
以下のPythonコードtest_pyflakes.py
に対してpyflakesを実行してみます。
import os a = b print({'key1': 1, 'key1': 2}) return 123
pyflakesはFlake8の既定のプラグインなので、flake8
コマンドを実行すればpyflakesによるチェックが行えます。実行してみます。
$ flake8 test_pyflakes.py test_pyflakes.py:1:1: F401 'os' imported but unused test_pyflakes.py:3:5: F821 undefined name 'b' test_pyflakes.py:4:8: F601 dictionary key 'key1' repeated with different values test_pyflakes.py:4:19: F601 dictionary key 'key1' repeated with different values test_pyflakes.py:5:1: F706 'return' outside function
pyflakesのF***
エラーが出力できました。
mccabe
mccabeは、Pythonコードの複雑度をチェックできるツールです。Flake8に既定のプラグインとして含まれていますが、既定では無効になっています。
flake8
コマンドの実行でmccabeによるチェックを行う場合は、次のように--max-complexity
スイッチを使用します。関数の複雑度がmax-complexity
の指定より大きい場合にC9XX
というエラーコードの警告が出力されます。
$ flake8 --max-complexity 10 coolproject
flake8-isort
flake8-isortは、Pythonコードでのファイルのインポート順が[isort documentation]に準拠しているかをチェックできるFlake8のプラグインです。
flake8-isortのインストール
flake8-isortのインストールはpip install
で行えます。インストールすることで自動的にFlake8のプラグインとして追加されます。
$ pip install flake8-isort
flake8-isortを実行してみる
以下のPythonコードtest_isort.py
に対してflake8-isortを実行してみます。
from os import path import os os.environ path.join('path', 'file')
flake8-isortはFlake8にプラグインとして追加済みなので、flake8
コマンドを実行すればflake8-isortによるチェックが行えます。実行してみます。
$ flake8 test_isort.py test_isort.py:2:1: I001 isort found an import in the wrong position
flake8-isortのI0**
エラーが出力できました。
なお、出力されるエラーコードの一覧は[flake8-isort - Error codes]で確認できます。
flake8-quotes
flake8-quotesは、Pythonコードでクォーテーションの利用がPEP 8に従っているかチェックできるFlake8のプラグインです。ダブルクォーテーションの不必要な使用をチェックしたい場合などに便利です。
flake8-quotesのインストール
flake8-quotesのインストールはpip install
で行えます。インストールすることで自動的にFlake8のプラグインとして追加されます。
$ pip install flake8-quotes
flake8-quotesを実行してみる
以下のPythonコードtest_quotes.py
に対してflake8-quotesを実行してみます。
print("test")
flake8-quotesはFlake8にプラグインとして追加済みなので、flake8
コマンドを実行すればflake8-quotesによるチェックが行えます。実行してみます。
$ flake8 test_quotes.py test_quotes.py:1:7: Q000 Remove bad quotes
flake8-quotesのQ0**
エラーが出力できました。
なお、出力されるエラーコードの一覧は[flake8-quotes - Warnings]で確認できます。
flake8-print
flake8-printは、PythonコードのPrintステートメントをチェックできるFlake8のプラグインです。print()の不必要な使用をチェックしたい場合などに便利です。
flake8-printのインストール
flake8-printのインストールはpip install
で行えます。インストールすることで自動的にFlake8のプラグインとして追加されます。
$ pip install flake8-print
flake8-printを実行してみる
以下のPythonコードtest_print.py
に対してflake8-printを実行してみます。
print('test')
flake8-printはFlake8にプラグインとして追加済みなので、flake8
コマンドを実行すればflake8-printによるチェックが行えます。実行してみます。
$ flake8 test_print.py test_print.py:1:1: T001 print found.
flake8-printのT0**
エラーが出力できました。
なお、出力されるエラーコードの一覧は[flake8-print - Error codes]で確認できます。
flake8-annotations
flake8-annotationsは、Pythonコードで関数が[PEP 3107 -- Function Annotations]と[PEP 484 -- Type Hints]に準拠しているかチェックできるFlake8のプラグインです。関数アノテーション(引数の指定など)が正しく行われているかをチェックしたい場合などに便利です。
flake8-annotationsのインストール
flake8-annotationsのインストールはpip install
で行えます。インストールすることで自動的にFlake8のプラグインとして追加されます。
$ pip install flake8-annotations
flake8-annotationsを実行してみる
以下のPythonコードtest_annotations.py
に対してflake8-annotationsを実行してみます。
a = 2 b = 1 def add_val(a, b): return a + b
flake8-annotationsはFlake8にプラグインとして追加済みなので、flake8
コマンドを実行すればflake8-annotationsによるチェックが行えます。実行してみます。
$ flake8 test_annotations.py test_annotations.py:5:13: ANN001 Missing type annotation for function argument 'a' test_annotations.py:5:16: ANN001 Missing type annotation for function argument 'b' test_annotations.py:5:19: ANN201 Missing return type annotation for public function
flake8-annotationsのANN***
エラーが出力できました。
なお、出力されるエラーコードの一覧は[flake8-annotations - Warnings]で確認できます。
flake8-mypy
flake8-mypyは、mypyによるPythonコードの静的な型チェックができるFlake8のプラグインです。関数アノテーション(型の一致など)が正しく行われているかをチェックしたい場合などに便利です。
flake8-mypyのインストール
flake8-mypyのインストールはpip install
で行えます。インストールすることで自動的にFlake8のプラグインとして追加されます。
$ pip install flake8-mypy
flake8-mypyを実行してみる
以下のPythonコードtest_mypy.py
に対してflake8-mypyを実行してみます。
a = 2 b = 1 def sub_val(a: int, b: int) -> str: return a - b
flake8-mypyはFlake8にプラグインとして追加済みなので、flake8
コマンドを実行すればflake8-mypyによるチェックが行えます。実行してみます。
$ flake8 test_mypy.py test_mypy.py:1:1: T499 Found 1 error in 1 file (checked 1 source file) test_mypy.py:6:13: T484 Incompatible return value type (got "int", expected "str")
flake8-mypyのT4**
エラーが出力できました。
なお、出力されるエラーコードの一覧は[flake8-mypy - List of warnings]で確認できます。
スタブがないとエラーになる場合がある
もしflake8
コマンドの実行時で以下のようなエラーが出たらスタブの設定をしてあげましょう。
$ flake8 test_mypy.py /usr/local/lib64/python3.6/site-packages is in the MYPYPATH. Please remove it. See https://mypy.readthedocs.io/en/latest/running_mypy.html#how-mypy-handles-imports for more info
実行環境がPython3のみであれば、ダミーのスタブファイルをMYPYPATH
に指定すれば動作はするようになるはずです。
$ touch path/to/dummy_stub.pyi $ export MYPYPATH=path/to/dummy_stub.pyi
そもそもスタブとは、型アノテーションをPython2系でも使えるように関数の型情報を外部ファイルに記載したものです。そしてmypy(もといflake8-mypy)で型チェックを行う際にこのスタブを参照する場合があり、見つからなければ前述のエラーとなるようです。型アノテーションにおけるスタブに関しては以下の記事が分かりやすかったです。
フォーマットツール
ここまで紹介してきたFlake8プラグインはコードチェックまでは行えますが、エラー箇所の自動修正まで行いたい場合は別途"コードフォーマットツール"を使う必要があります。
ここでは、いくつかのコードフォーマットツールを実際に使ってコードの自動修正をしてみます。
isort
isortは、Pythonインポートをアルファベット順に並び替えるツールです。(並び替えるので "I sort" です。)
isortのインストール
isortのインストールはpip install
で行えます。
$ pip install isort
isortを実行してみる
以下のPythonコードtest_isort.py
を対象とします。
from os import path import os os.environ path.join('path', 'file')
isort実行前はflake8_isortのチェックで以下のようにI001
エラーが出力されています。
$ flake8 test_isort.py test_isort.py:2:1: I001 isort found an import in the wrong position
isortを実行してみます。
$ isort test_isort.py Fixing /home/ec2-user/environment/test_isort.py
Pythonコードtest_isort.py
が以下のように修正されました。
import os from os import path os.environ path.join('path', 'file')
isort実行後はflake8_isortのチェックでエラーが出力されなくなりました。
$ flake8 test_isort.py
autopep8
autopep8は、PEP 8スタイルガイドに準拠するようにPythonコードを自動的にフォーマットするツールです。
autopep8のインストール
autopep8のインストールはpip install
で行えます。
$ pip install autopep8
autopep8を実行してみる
以下のPythonコードtest_pycodestyle.py
を対象とします。
import os, json a = os.getcwd() b = [json.dumps(1),2, 3 ]
autopep8実行前はpycodestyleのチェックで以下のようにE***
とW***
エラーが出力されています。
$ flake8 test_pycodestyle.py test_pycodestyle.py:1:1: I001 isort found an import in the wrong position test_pycodestyle.py:1:10: E401 multiple imports on one line test_pycodestyle.py:2:1: I003 isort expected 1 blank line in imports, found 0 test_pycodestyle.py:2:4: E222 multiple spaces after operator test_pycodestyle.py:5:19: E231 missing whitespace after ',' test_pycodestyle.py:5:24: E202 whitespace before ']' test_pycodestyle.py:5:26: W292 no newline at end of file
autopep8を実行すると、フォーマット後のコードが出力されます。
$ autopep8 test_pycodestyle.py import os import json a = os.getcwd() b = [json.dumps(1), 2, 3]
--in-place
オプションを付けてautopep8を実行すると、ファイルのコードが実際にフォーマットされます。
$ autopep8 --in-place test_pycodestyle.py
Pythonコードtest_pycodestyle.py
が以下のようにフォーマットされました。
import os import json a = os.getcwd() b = [json.dumps(1), 2, 3]
autopep8実行後はpycodestyleのチェックでE***
とW***
エラーが出力されなくなりました。
$ flake8 test_pycodestyle.py test_pycodestyle.py:2:1: I001 isort found an import in the wrong position test_pycodestyle.py:3:1: I003 isort expected 1 blank line in imports, found 0
autopep8がフォーマットするエラー一覧は[autopep8 - Features]で確認できます。
autoflake
autoflakeは、未使用のインポートや変数をPythonコードから削除するツールです。
autoflakeのインストール
autoflakeのインストールはpip install
で行えます。
$ pip install autoflake
autoflakeを実行してみる
以下のPythonコードtest_autoflake.py
を対象とします。
import math import subprocess import sys def foo() -> str: from abc import ABCMeta, WeakSet try: import multiprocessing return str(multiprocessing.cpu_count()) except ImportError as exception: return sys.version
autoflake実行前はpyflakesのチェックで以下のようにF***
とT***
エラーが出力されています。
$ flake8 test_autoflake.py test_autoflake.py:1:1: F401 'math' imported but unused test_autoflake.py:1:1: T499 Found 1 error in 1 file (checked 1 source file) test_autoflake.py:2:1: F401 'subprocess' imported but unused test_autoflake.py:7:5: F401 'abc.ABCMeta' imported but unused test_autoflake.py:7:5: F401 'abc.WeakSet' imported but unused test_autoflake.py:7:6: T484 Module 'abc' has no attribute 'WeakSet' test_autoflake.py:11:5: F841 local variable 'exception' is assigned to but never used
autoflakeでは未使用の変数の自動フォーマットは既定では無効です。フォーマットの対象とするためには--remove-unused-variables
オプションを使う必要があります。実行すると、フォーマット後のコードが出力されます。
$ autoflake --remove-unused-variables test_autoflake.py --- original/test_autoflake.py +++ fixed/test_autoflake.py @@ -1,12 +1,9 @@ -import math -import subprocess import sys def foo() -> str: - from abc import ABCMeta, WeakSet try: import multiprocessing return str(multiprocessing.cpu_count()) - except ImportError as exception: + except ImportError: return sys.version
--in-place
オプションを付けてautoflakeを実行すると、ファイルのコードが実際にフォーマットされます。
$ autoflake --in-place --remove-unused-variables test_autoflake.py
Pythonコードtest_autoflake.py
が以下のようにフォーマットされました。
import sys def foo() -> str: try: import multiprocessing return str(multiprocessing.cpu_count()) except ImportError: return sys.version
再度pyflakesでチェックすると、エラーが出力されなくなりました。
$ flake8 test_autoflake.py test_autoflake.py:1:1: T499 Success: no issues found in 1 source file
まとめ
今回紹介したコードのチェックツール(Flake8プラグイン)、フォーマットツールおよび実際のエラーの対応関係をまとめると以下のようになります。
チェックツール | エラーコード | エラーの説明 | フォーマットツール(※) |
---|---|---|---|
pycodestyle | E1** |
Indentation | autopep8 |
E2** |
Whitespace | autopep8 | |
E3** |
Blank line | autopep8 | |
E4** |
Import | autopep8 | |
E5** |
Line length | autopep8 | |
E7** |
Statement | autopep8 | |
E9** |
Runtime | autopep8 | |
W1** |
Indentation warning | ||
W2** |
Whitespace warning | autopep8 | |
W3** |
Blank line warning | autopep8 | |
W5** |
Line break warning | autopep8 | |
W6** |
Deprecation warning | autopep8 | |
pyflakes | F4** |
import etc | autoflake |
F6** |
invalid use etc | ||
F7** |
statement etc | ||
F8** |
name etc | ||
F9** |
raise etc | ||
mccabe | C9** |
complexity | |
flake8-isort | I0** |
import sort | isort |
flake8-quotes | Q0** |
quote | |
flake8-print | T0** |
||
flake8-annotations | ANN0** |
Function Annotations | |
ANN1** |
Method Annotations | ||
ANN2** |
Return Annotations | ||
ANN3** |
Type Comments | ||
flake8-mypy | T*** |
typing |
※同エラーコード中でも一部未対応のエラーがあります。(例えば、autopep8はE1**
エラー中の一部にのみ対応しています)
おわりに
以上、Python向けのLintツール「Flake8」と、それに対応するプラグインやフォーマットツールについてのご紹介でした。
プラグインで機能を拡張していくというFlake8の思想が調べていてとても面白かったです。(あと"プラグイン"という響きがなんだかかっこいい)
今回紹介したプラグインやツールの一部でも使いこなして、プロジェクトでの開発/運用の効率をアップさせていきたいですね。
参考
以上